Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full rewrite. Supports mouse, multimedia keys, auto-reconnect, etc. #11

Open
wants to merge 592 commits into
base: master
Choose a base branch
from

Conversation

quaxalber
Copy link

Hey @HeuristicPerson

Thanks so much for your project. It helped me getting started. Since I needed to relay both keyboard and mouse , I decided to build my own solution on top. Feel free to pull if you like it.

Cheers

This was referenced Oct 11, 2023
@ig-sinicyn
Copy link

ig-sinicyn commented Nov 11, 2023

Hi!
@quaxalber , I've tried this version and I want to say a huge thanks for it! Works (almost) first try, no serious issues so far.

There are some minor ones. I cannot report them in the fork repo, so here it goes:

  1. For clean installation on RPi4 (lite os), there is no evdev module installed and the one in submodules does not work, no idea why. The bluetooth_2_usb.py -l fails something like "No module named 'evdev'" error. I cannot find exact message now but I may try to reproduce it if you're interested. Was workarounded with sudo apt install python3-evdev.
  2. Service does not start if keyboard or mouse is disconnected, it fails with FileNotFoundError. That's a pain if you use keyboard with multiple devices. Also, it looks like there is support for disconnected devices after service start but not at the startup time.
Output if no device connected

igors@hid-bridge:~/bluetooth_2_usb $ sudo python3.11 bluetooth_2_usb.py -k /dev/input/event2
23-11-11 21:40:56 [INFO] Launching Bluetooth 2 USB v0.4.4
23-11-11 21:40:58 [ERROR] Failed to initialize devices.
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 125, in __init__
    fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 80, in _init_devices
    self._create_and_register_links(keyboard_paths, mouse_paths)
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in _create_and_register_links
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in <listcomp>
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 148, in create_keyboard_link
    return self._create_device_link(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 167, in _create_device_link
    input_device = InputDevice(input_device_path)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 127, in __init__
    fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'
23-11-11 21:40:58 [ERROR] Houston, we have an unhandled problem. Abort mission.
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 125, in __init__
    fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 413, in <module>
    asyncio.run(_main())
  File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 386, in _main
    proxy = ComboDeviceHidProxy(args.keyboards, args.mice, args.sandbox)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 62, in __init__
    self._init_devices(keyboard_paths, mouse_paths, is_sandbox)
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 80, in _init_devices
    self._create_and_register_links(keyboard_paths, mouse_paths)
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in _create_and_register_links
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 133, in <listcomp>
    keyboards = [self.create_keyboard_link(path) for path in keyboard_paths]
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 148, in create_keyboard_link
    return self._create_device_link(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/igors/bluetooth_2_usb/bluetooth_2_usb.py", line 167, in _create_device_link
    input_device = InputDevice(input_device_path)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/evdev/device.py", line 127, in __init__
    fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/dev/input/event2'

@ig-sinicyn
Copy link

ig-sinicyn commented Nov 12, 2023

Okay, I've managed to workaround the second issue but the fix is really ugly.
I'm not a python dev and it works for me so I'd call it a day:)

@quaxalber
Copy link
Author

quaxalber commented Nov 14, 2023

Hey @ig-sinicyn

Thanks a lot for your feedback!

I was aware of both these issues. In fact the second one already had a dedicated issue in my fork. Cool that you figured out a solution yourself right away! Feel free to PR your fix so this one may be closed.

The first one got introduced when I switched from evdev PyPI package to my own submodule, since I wanted to be able to modify it. This one needs investigating why the submodule is not working properly. If you have a clue please let me know in this new issue!

I cannot report them in the fork repo,

Could you please explain? Do you mean my fork or yours?

Cheers

@ig-sinicyn
Copy link

ig-sinicyn commented Nov 14, 2023

Hi @quaxalber! :)

I'm really glad the feedback was well-received. The bridge works with no issues, no reboots or hiccups so far. The only thing I've noticed, the state of NumLock/CapsLock is not synchronised with device the RaspberryPi is attached to. I've did not investigated it deeper so far so I'm not sure where the real problem is. It may be my device, raspberry, my keyboard or all of them:)

Could you please explain? Do you mean my fork or yours?

Well, it was my fault:) I've refreshed your's fork page and the issues tab appeared. I thought there's no issues for the forks, my bad.

quaxalber and others added 30 commits December 12, 2023 15:05
Make user owner of all files in repo
* Implemented grabbing input device

* Chmod scripts executable

* Bump version

* Chmod main script executable

* Use shell wrapper script that activates venv
Add pip constraints

* Chmod scripts

* Remove dot imports

* Add blank line

* Modify log messages

* Bump version

* Update performs a clean reinstall

* Fix executable path

* Preserve repo ownership

* Fix stat dir

* Remove constraints

* Re-enable constraints

* Preserve currently checked out branch

* Add cleanup function

* Add cd to parent dir

* Adapt reboot hint

* Adapt to latest script changes

* Remove unnecessary blank lines

* Update to v0.6.6

* Add adafruit-circuitpython-typing

* Set fixed version

* Fix missing =

* Reduce delays

* Keep track of relayed devices

* Add debug output

* Initialize gadgets once and share across module

* Move device functions to __init__.py

* Move device functions back to relay.py

* Remove temporary debug output
Bump version

* Defer USB device init

* Check gadget state on relay init
Rename symbols

* Improve gadget init debug output

* Update to v0.6.7

* Show versions before updating

* Change to project dir first

* Use variables instead of hard-coded paths

* Make user owner of all files

* Leave chmod to install.sh

* Preserve ownership before installing

* Bump version

---------

Co-authored-by: Hannes U @cylonid 
Co-authored-by: Benjamin T @quaxalber
* Use asyncio.all_tasks() again to check if relay is active

* Add missing type hints

* Add Arguments class with typed properties

* Reformat help texts

* Unify punctuation

* Print help arg last

* Re-add print_help()

* Rearrange help args

* Update docs to v0.7.1

* Bump version
* Add Arguments.__str__()

* Move arg setup to CustomArgumentParser
* Add Arguments.__str__()

* Move arg setup to CustomArgumentParser

* Fix object representations
Fix type hints

* Fix variable name

* Fix relay str representation

* Bump version

* Run git fetch before tag

* Log signal name instead of int on shutdown

* Re-add sys.exit(0) in signal handler
* Make venv dir non-hidden
* Fix device representation

* Remove str cast

* Fix debug output

* Bump version
* Update docs to v0.7.4
* Build Arguments.__str__() dynamically

* Update docs
* Move intro to top

* Specify RPi OS as mandatory requirement

* Specify RPi OS Bookworm

* Add link to RPi OS Bookworm blog post
* Clean up DeviceIdentifier

* Add missing imports
* Set new overview image

* Update overview image license
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants